package com.acme.bankapp.service.bank;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.acme.bankapp.domain.bank.Account;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.CheckingAccount;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.exceptions.NotEnoughFundsException;

public class BankReport {
	static final String MES_NULL_BANK_VARIABLE = "Object reference do not set to an instance of Bank object";
	
	static final String MES_CLIENTS_NUMBER = "Number of clients = ";
	static final String MES_ACCOUNTS_NUMBER = "Number of accounts = ";
	static final String MES_ACCOUNTS_SORTED_LIST = "Accounts sorted by balance:";
	static final String MES_BANK_CREDIT = "Total value of bank credit = ";
	static final String MES_CLIENT_ACCOUNTS_LIST = "Accounts of clients:";
	
	
	public static int getNbOfCustomers(Bank bank) throws IllegalArgumentException {
		if (bank == null)
			throw new IllegalArgumentException(MES_NULL_BANK_VARIABLE);
		
		return bank.getClients().size();
	}
	
	public static int getNbOfAccounts(Bank bank) throws IllegalArgumentException {
		if (bank == null)
			throw new IllegalArgumentException(MES_NULL_BANK_VARIABLE);
		
		int count = 0;
		for (Client client : bank.getClients()) {
			count += client.getAccounts().size();
		}
		
		return count;
	}
	
	public static List<Account> getAccountsSortedBySum(Bank bank) throws IllegalArgumentException {
		if (bank == null)
			throw new IllegalArgumentException(MES_NULL_BANK_VARIABLE);
		
		List<Account> list = new ArrayList<>(getNbOfAccounts(bank));
		for (Client client : bank.getClients()) {
			list.addAll(client.getAccounts());
		}
		
		Collections.sort(list, new Comparator<Account>() {
			@Override
			public int compare(Account o1, Account o2) {
				return (int)(o1.getBalance() - o2.getBalance());
			}});
		
		return list;
	}
	
	public static double getBankCredit(Bank bank) throws IllegalArgumentException {
		if (bank == null)
			throw new IllegalArgumentException(MES_NULL_BANK_VARIABLE);
		
		double credit = 0;
		for (Client client : bank.getClients()) {
			for (Account account : client.getAccounts()) {
				if (account instanceof CheckingAccount) {
					double balance = account.getBalance();
					if (balance < 0)
						credit -= balance;					
				}
			}
		}
		
		return credit;
	}
	
	public static Map<Client, List<Account>> getCustomerAccounts(Bank bank) throws IllegalArgumentException {
		if (bank == null)
			throw new IllegalArgumentException(MES_NULL_BANK_VARIABLE);
		
		Map<Client, List<Account>> map = new HashMap<>();
		
		for (Client client : bank.getClients()) {
			map.put(client, new ArrayList<>(client.getAccounts()));
		}
		
		return map;
	}
	
	public static void printStatistic(Bank bank) {
		System.out.println(MES_CLIENTS_NUMBER + getNbOfCustomers(bank));
		System.out.println(MES_ACCOUNTS_NUMBER + getNbOfAccounts(bank));
		System.out.println(MES_ACCOUNTS_SORTED_LIST);
		for (Account account : getAccountsSortedBySum(bank))
			System.out.println(account);
		
		System.out.println(MES_BANK_CREDIT + getBankCredit(bank));
		System.out.println(MES_CLIENT_ACCOUNTS_LIST);
		Map<Client, List<Account>> map = getCustomerAccounts(bank);
		for (Client client : map.keySet()) {
			System.out.println(client.getClientSalutation());
			for (Account account : map.get(client)) {
				System.out.println(account);
			}
		}
	}
}
